package show.me.the.money.service.dao;

import java.util.HashMap;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.springframework.beans.BeansException;
import org.springframework.web.context.WebApplicationContext;

import show.me.the.money.dao.exception.DataAccessException;
import show.me.the.money.service.core.Service;
import show.me.the.money.util.context.Context;


public abstract class DBSupportService extends DBService {
	
	protected boolean transactionSupport = false;
	
	public void execute(HashMap<String, Object> req,HashMap<String, Object> res, Context ctx) {
		int code = 200;
		String msg = "Success";
		Session ss = null;
		if(ctx.has(Context.DB_SESSION)){
			ss = (Session)ctx.get(Context.DB_SESSION);
		}
		else{
			try{
				WebApplicationContext wac = (WebApplicationContext)ctx.get(Context.APP_CONTEXT);
				if(wac == null){
					code = 505;
					msg = "WebApplicationContextNotFound";
				}
				else{
					SessionFactory sf = (SessionFactory)wac.getBean("mySessionFactory");
					ss = sf.openSession();
					ctx.put(Context.DB_SESSION, ss);
					//this.fireEvent("afterSessionOpen", new HashMap<String,Object>().put(Context.DB_SESSION, ss));
				}
			}
			catch(BeansException e){
				code = 504;
				msg = "LookupmySessionFactoryBeanFailed";
			}
			catch(HibernateException e){
				code = 509;
				msg = "OpenDBSessionFalied";
			}
		}
		
		if(ss != null){
			Transaction trx = null;
			try{
				if(transactionSupport){
					trx = ss.getTransaction();
					trx.begin();
				}
				dbSupportExecute(req,res,ctx);
				if(trx != null){
					trx.commit();
				}
			}
			catch(DataAccessException e){
				code = 501;
				msg = "DataAccessException:" + e.getMessage();
				if(trx != null){
					trx.rollback();
				}
			}
			catch(Exception e){
				code = 599;
				msg = "UnkonwException:" + e.getMessage();
				if(trx != null){
					trx.rollback();
				}
			}
			finally{
//				if(ss != null && ss.isOpen()){
//					ss.close();
//				}
			}
		}
		res.put(Service.RES_CODE,code);
		res.put(Service.RES_MESSAGE,msg);
	}
	
	public void setTransactionSupport(boolean status){
		transactionSupport = status;
	}
	
	public abstract void dbSupportExecute(HashMap<String, Object> req,HashMap<String, Object> res, Context ctx) throws DataAccessException;
}
